package at.fhj.itm10.ticketmaster.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.apache.log4j.Logger;

import at.fhj.itm10.ticketmaster.entities.Address;

/**
 * Address DAO.
 * 
 * @author stefan leisenberger
 */
public class AddressDAO extends AbstractDAO implements AddressDAOInterface {
	
	/**
	 * Must be an integer in the database.
	 */
	private final static String PRIMARYKEY_NAME = "id";

	private final static String SQL_INSERT ="INSERT INTO `address`(`name`, `street`, `zip`, `city`, `country`) VALUES(?,?,?,?,?)";
	
	private final static String SQL_UPDATE = "UPDATE `address` SET `name` = ?, `street` = ?, `zip` = ?, `city` = ?, `country` = ? WHERE `id` = ?";
	
	private final static String SQL_DELETE = "DELETE FROM `address` WHERE `id` = ?";
	
	private final static String SQL_FINDBYID = "SELECT * FROM `address` WHERE `id` = ?";
	
	private final static String SQL_FINDBYCITY = "SELECT * FROM `address` WHERE `city` = ?";
	
	private final static String SQL_FINDALL = "SELECT * FROM `address`";
	
	private Logger logger = Logger.getLogger(AddressDAO.class);
	
	public AddressDAO(Connection connection) throws DAOException {
		super(connection);
	}

	/**
	 * {@inheritDoc}
	 */
	public void insert(Address entity) throws DAOException {
		logger.debug("AddressDAO.insert(Address = " + entity.toString() + ")");
		checkForValidEntity(entity);
		PreparedStatement statement = prepareStatement(SQL_INSERT);
		
		try {
			statement.setString(1, entity.getName());
			statement.setString(2, entity.getStreet());
			statement.setString(3, entity.getZip());
			statement.setString(4, entity.getCity());
			statement.setString(5, entity.getCountry());
		} catch (SQLException e) {
			logger.error("failed to insert: " + entity.toString());
			throw new DAOException(e);
		}
		
		super.processInsert(statement, entity);
	}
	
	/**
	 * {@inheritDoc}
	 */
	public void update(Address entity) throws DAOException {
		logger.debug("AddressDAO.update(Address = " + entity.toString() + ")");
		checkForValidEntity(entity);
		PreparedStatement statement = prepareStatement(SQL_UPDATE);
		
		try {
			statement.setString(1, entity.getName());
			statement.setString(2, entity.getStreet());
			statement.setString(3, entity.getZip());
			statement.setString(4, entity.getCity());
			statement.setString(5, entity.getCountry());
			statement.setLong(6, entity.getId());
		} catch (SQLException e) {
			logger.error("failed to update: " + entity.toString());
			throw new DAOException(e);
		}
		
		super.processUpdate(statement, entity);
	}

	/**
	 * {@inheritDoc}
	 */
	public void delete(Address entity) throws DAOException {
		logger.debug("AddressDAO.delete(Address = " + entity.toString() + ")");
		checkForValidEntity(entity);

		super.doDelete(prepareStatement(SQL_DELETE), entity);
	}

	/**
	 * {@inheritDoc}
	 */
	public Address findById(long id) throws DAOException {
		logger.debug("AddressDAO.findById(long = " + id + ")");
		Address entity = (Address) retrieveEntity(id);
		if (entity != null) {
			return entity;
		}

		return (Address) super.doFindOne(id, prepareStatement(SQL_FINDBYID));
	}

	/**
	 * {@inheritDoc}
	 */
	public List<Address> findByCity(String city) throws DAOException {
		logger.debug("AddressDAO.findByCity(String = " + city + ")");
		if (city == null) {
			logger.error("parameter city is null");
			throw new NullPointerException("city is null");
		}
		
		PreparedStatement statement = prepareStatement(SQL_FINDBYCITY);

		try {
			statement.setString(1, city);
		} catch (SQLException e) {
//			logger.error("error finding city: " + city);
			throw new DAOException(e);
		}

		return super.doFindMore(PRIMARYKEY_NAME, statement);
	}

	/**
	 * {@inheritDoc}
	 */
	public List<Address> findAll() throws DAOException {
		logger.debug("AddressDAO.findAll()");
		return super.doFindMore(PRIMARYKEY_NAME, prepareStatement(SQL_FINDALL));
	}

	/**
	 * {@inheritDoc}
	 */
	protected Address fillEntityByResult(ResultSet resultSet) throws DAOException {
		logger.debug("AddressDAO.fillEntityByResult(Resultset = " + resultSet.toString() + ")");
		Address address = new Address();
		
		try {
			address.setId(resultSet.getLong(PRIMARYKEY_NAME));
			address.setName(resultSet.getString("name"));
			address.setStreet(resultSet.getString("street"));
			address.setZip(resultSet.getString("zip"));
			address.setCity(resultSet.getString("city"));
			address.setCountry(resultSet.getString("country"));
		} catch (SQLException e) {
			logger.error("cant fill entity by result: " + resultSet.toString());
			throw new DAOException(e);
		}

		return address;
	}
}